package archer.back.models

import java.util.Date

import archer.back.utils.PoiStyles
import models.CrawlTables._
import cats.implicits._
import models.{ CusPoiOperations, UrlWrap }
import net.scalax.cpoi.api._
import writers._

import scala.annotation.tailrec

class CrawlResultModel(
  updateCrawlActionRow: UpdateCrawlActionRow,
  updateTreeNodeRows: List[UpdateTreeNodeRow],
  currentDate: Date)
  extends CusPoiOperations {

  val errActionCell = (if (updateCrawlActionRow.isSuccessed === Option(true)) {
    CPoi
      .wrapData("空栏目")
      .addTransform(PoiStyles.TextFormat())
  } else {
    CPoi
      .wrapData("任务未完成或任务出错")
      .addTransform(PoiStyles.TextFormat())
  }).untyped

  @tailrec
  private def nodeListGen(
    currentId: Int,
    currentList: List[UpdateTreeNodeRow]): List[UpdateTreeNodeRow] = {
    updateTreeNodeRows.find(_.id === currentId) match {
      case Some(current) =>
        nodeListGen(current.parentId, current :: currentList)
      case _ =>
        currentList
    }
  }

  def nodeList = {
    nodeListGen(updateCrawlActionRow.treeNodeId, List.empty)
  }

  //最新结果距今多少小时
  val hoursLeft = updateCrawlActionRow.updateTime.map(time =>
    (currentDate.getTime - time.getTime) / (1000 * 60 * 60).toLong)
  //最新结果距今多少天
  val dayssLeft = hoursLeft.map(hours => hours / 24)
  //期望发布频率（日）
  val delayDays = updateCrawlActionRow.delayHours / 24

  def nodeName =
    PoiKey(
      CrawlResultModel.t1,
      CPoi.wrapData(
        updateTreeNodeRows
          .find(_.id === updateCrawlActionRow.treeNodeId)
          .map(_.name)
          .getOrElse("")))

  def modifiedTime =
    PoiKey(
      CrawlResultModel.t2,
      CPoi
        .wrapData(updateCrawlActionRow.modifiedTime: java.util.Date)
        .addTransform(PoiStyles.DateFormat("yyyy年MM月dd日HH时mm分ss秒")))

  def lastUpdateTime =
    PoiKey(
      CrawlResultModel.t3,
      updateCrawlActionRow.updateTime
        .map { time =>
          CPoi
            .wrapData(time: java.util.Date)
            .addTransform(PoiStyles.DateFormat("yyyy年MM月dd日HH时mm分ss秒"))
        }
        .getOrElse {
          errActionCell
        })

  def currentTime =
    PoiKey(
      CrawlResultModel.t4,
      CPoi
        .wrapData(currentDate)
        .addTransform(PoiStyles.DateFormat("yyyy年MM月dd日HH时mm分ss秒")))

  def dayLeft =
    PoiKey(
      CrawlResultModel.t5,
      dayssLeft
        .map { days =>
          CPoi
            .wrapData(days.toDouble) //.addTransform(PoiStyles.TextFormat())
        }
        .getOrElse { errActionCell })

  def poiDelayDays =
    PoiKey(CrawlResultModel.t6, CPoi.wrapData(delayDays.toDouble)) //.addTransform(PoiStyles.TextFormat())

  def expect =
    PoiKey(
      CrawlResultModel.t7,
      dayssLeft
        .map { days =>
          CPoi
            .wrapData((delayDays - days).toDouble)
          //.addTransform(PoiStyles.TextFormat())
        }
        .getOrElse { errActionCell })

  def firstNewsTitle =
    PoiKey(
      CrawlResultModel.t8,
      updateCrawlActionRow.newsTitle
        .map(
          title =>
            CPoi
              .wrapData(title)
              .addTransform(PoiStyles.TextFormat()))
        .getOrElse {
          errActionCell
        })

  val urlToShow =
    if (updateCrawlActionRow.url.size > 40)
      updateCrawlActionRow.url.take(36) + "..."
    else updateCrawlActionRow.url

  def url =
    PoiKey(
      CrawlResultModel.t9,
      CPoi
        .wrapData(UrlWrap(showText = urlToShow, url = updateCrawlActionRow.url))
        .addTransform(PoiStyles.TextFormat()))

  def lawUrl =
    CPoi
      .wrapData(updateCrawlActionRow.url)
      .addTransform(PoiStyles.TextFormat())

  val dataList = List(
    nodeName,
    modifiedTime,
    lastUpdateTime,
    currentTime,
    dayLeft,
    poiDelayDays,
    expect,
    firstNewsTitle,
    url) ::: {
    CrawlResultModel.nTotal
      .zip(nodeList)
      .map {
        case (key, node) =>
          PoiKey(
            key,
            CPoi
              .wrapData(node.name)
              .addTransform(PoiStyles.TextFormat()))
      }
  }

  val map = dataList.map(s => s.key -> s.value).toMap

  def lineList(colNames: List[String]): List[CellDataAbs] = {
    colNames.map { key =>
      map.get(key).getOrElse(CPoi.wrapData("").untyped)
    }
  }

}

case class PoiKey(key: String, value: CellDataAbs)

object CrawlResultModel {

  val t1 = "Node 名称"
  val t2 = "抓取启动时间"
  val t3 = "最近更新时间"
  val t4 = "目前时间"
  val t5 = "最新结果距今天数"
  val t6 = "期望发布频率（日）"
  val t7 = "期望差"
  val t8 = "最新结果标题"
  val t9 = "链接"

  val n1 = "第一级 Node"
  val n2 = "第二级 Node"
  val n3 = "第三级 Node"
  val n4 = "第四级 Node"
  val n5 = "第五级 Node"
  val n6 = "第六级 Node"
  val n7 = "第七级 Node"
  val n8 = "第八级 Node"
  val n9 = "第九级 Node"
  val n10 = "第十级 Node"

  val nTotal = n1 :: n2 :: n3 :: n4 :: n5 :: n6 :: n7 :: n8 :: n9 :: n10 :: Nil
  val total = t1 :: t2 :: t3 :: t4 :: t5 :: t6 :: t7 :: t8 :: t9 :: nTotal

}
